/**
 * @file lv_port_indev_templ.c
 *
 */

/*Copy this file as "lv_port_indev.c" and set this value to "1" to enable content*/
#ifndef EN_MOUSE

/*********************
 *      INCLUDES
 *********************/
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#include "lv_port_indev_touch_screen.h"
#include "sdl_render.h"


/*********************
 *      DEFINES
 *********************/

/**********************
 *      TYPEDEFS
 **********************/
struct touch_data
{
    sdl_event_handle_arr_t  eventsInfo;
    SDL_Event               cur;
    SDL_Point               prvePos;
};

/**********************
 *  STATIC PROTOTYPES
 **********************/

static void touchpad_read(lv_indev_t * indev, lv_indev_data_t * data);
static bool touchpad_is_pressed(struct touch_data *);
static void touchpad_get_xy(struct touch_data *, int32_t * x, int32_t * y);

static void button_init(void);
static void button_read(lv_indev_t * indev, lv_indev_data_t * data);
static int8_t button_get_pressed_id(void);
static bool button_is_pressed(uint8_t id);

static void touch_event(const SDL_Event *, void *, void *);

/**********************
 *  STATIC VARIABLES
 **********************/
lv_indev_t * indev_encoder;
lv_indev_t * indev_button;

static int32_t encoder_diff;
static lv_indev_state_t encoder_state;

static sdl_event_handle_t events[] = {
    { .type = SDL_MOUSEMOTION, .fn = touch_event, .arg = NULL },
    { .type = SDL_MOUSEBUTTONDOWN, .fn = touch_event, .arg = NULL },
    { .type = SDL_MOUSEBUTTONUP, .fn = touch_event, .arg = NULL },
};

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

void lv_port_indev_touch_screen_init(void)
{
    /*Initialize your touchpad if you have*/

    struct touch_data * p = malloc(sizeof(*p));
    if (p == NULL)  return;
    bzero(p, sizeof(*p));

    /*Register a touchpad input device*/
    lv_indev_t * indev_touchpad = lv_indev_create();
    lv_indev_set_type(indev_touchpad, LV_INDEV_TYPE_POINTER);
    lv_indev_set_read_cb(indev_touchpad, touchpad_read);
    lv_indev_set_driver_data(indev_touchpad, p);

    p->eventsInfo.lvglDrv = indev_touchpad;
    p->eventsInfo.arr = events;
    p->eventsInfo.arrlen = sizeof(events) / sizeof(events[0]);

    void * handle = lv_display_get_driver_data(lv_indev_get_display(indev_touchpad));
    sdl_event_listen(handle, &p->eventsInfo);
}


/**********************
 *   STATIC FUNCTIONS
 **********************/

/*------------------
 * Touchpad
 * -----------------*/

static void touch_event(const SDL_Event * e, void * lvglDrv, void * arg)
{
    (void) arg;

    struct touch_data * p = lv_indev_get_driver_data(lvglDrv);
    int saveDataFlg = 0;

    if ((e->type == SDL_MOUSEBUTTONUP) || (e->type == SDL_MOUSEBUTTONDOWN))
    {
        if (e->button.button == 1)  // 是鼠标左键
        {
            p->cur = *e;
            saveDataFlg = 1;
        }
    }
    else if (e->type == SDL_MOUSEMOTION)
    {
        saveDataFlg = 1;
    }

    if (saveDataFlg)
    {
        p->prvePos.x = e->motion.x;
        p->prvePos.y = e->motion.y;
    }
}


/*Will be called by the library to read the touchpad*/
static void touchpad_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
{
    static int32_t last_x = 0;
    static int32_t last_y = 0;

    struct touch_data * p = lv_indev_get_driver_data(indev_drv);

    /*Save the pressed coordinates and the state*/
    if(touchpad_is_pressed(p)) {
        touchpad_get_xy(p, &last_x, &last_y);
        data->state = LV_INDEV_STATE_PRESSED;
    }
    else {
        data->state = LV_INDEV_STATE_RELEASED;
    }

    /*Set the last pressed coordinates*/
    data->point.x = last_x;
    data->point.y = last_y;
}

/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(struct touch_data * p)
{
    /*Your code comes here*/

    if (p->cur.button.state == SDL_PRESSED)
    {
        return true;
    }

    return false;
}

/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(struct touch_data * p, int32_t * x, int32_t * y)
{
    /*Your code comes here*/

    *x = p->prvePos.x;
    *y = p->prvePos.y;
}


/*------------------
 * Button
 * -----------------*/

/*Initialize your buttons*/
static void button_init(void)
{
    /*Your code comes here*/
}

/*Will be called by the library to read the button*/
static void button_read(lv_indev_t * indev_drv, lv_indev_data_t * data)
{
    (void) indev_drv;

    static uint8_t last_btn = 0;

    /*Get the pressed button's ID*/
    int8_t btn_act = button_get_pressed_id();

    if(btn_act >= 0) {
        data->state = LV_INDEV_STATE_PRESSED;
        last_btn = btn_act;
    }
    else {
        data->state = LV_INDEV_STATE_RELEASED;
    }

    /*Save the last pressed button's ID*/
    data->btn_id = last_btn;
}

/*Get ID  (0, 1, 2 ..) of the pressed button*/
static int8_t button_get_pressed_id(void)
{
    uint8_t i;

    /*Check to buttons see which is being pressed (assume there are 2 buttons)*/
    for(i = 0; i < 2; i++) {
        /*Return the pressed button's ID*/
        if(button_is_pressed(i)) {
            return i;
        }
    }

    /*No button pressed*/
    return -1;
}

/*Test if `id` button is pressed or not*/
static bool button_is_pressed(uint8_t id)
{
    (void) id;

    /*Your code comes here*/

    return false;
}

#else /*Enable this file at the top*/

/*This dummy typedef exists purely to silence -Wpedantic.*/
typedef int keep_pedantic_happy;
#endif
